package com.googlecode.restitory.gae.rhino;

import java.lang.reflect.InvocationTargetException;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RhinoLog extends ScriptableObject {

	private static final Logger LOG = LoggerFactory.getLogger(RhinoLog.class);

	private static final long serialVersionUID = 3129065618782749972L;

	@Override
	public String getClassName() {
		return "Console";
	}

	public static void jsFunction_info(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
		if (args.length == 0) {
			LOG.info("");
		}
		StringBuilder buf = concat(args);
		Object last = args[args.length - 1];
		if (last instanceof Throwable) {
			LOG.info(buf.toString(), last);
		} else {
			LOG.info(buf.append(last).toString());
		}
	}

	public static void jsFunction_debug(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
		if (args.length == 0) {
			LOG.info("");
		}
		StringBuilder buf = concat(args);
		Object last = args[args.length - 1];
		if (last instanceof Throwable) {
			LOG.debug(buf.toString(), last);
		} else {
			LOG.debug(buf.append(last).toString());
		}
	}

	public static void jsFunction_error(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
		if (args.length == 0) {
			LOG.info("");
		}
		StringBuilder buf = concat(args);
		Object last = args[args.length - 1];
		if (last instanceof Throwable) {
			LOG.error(buf.toString(), last);
		} else {
			LOG.error(buf.append(last).toString());
		}
	}

	public static void jsFunction_warn(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
		if (args.length == 0) {
			LOG.info("");
		}
		StringBuilder buf = concat(args);
		Object last = args[args.length - 1];
		if (last instanceof Throwable) {
			LOG.warn(buf.toString(), last);
		} else {
			LOG.warn(buf.append(last).toString());
		}
	}

	private static StringBuilder concat(Object[] args) {
		StringBuilder buf = new StringBuilder();
		for (int i = 0; i < args.length - 1; i++) {
			buf.append(args[i]).append(' ');
		}
		return buf;
	}

	public static void config(ScriptableObject scope, Context ctx) {
		try {
			ScriptableObject.defineClass(scope, RhinoLog.class);
			Scriptable console = ctx.newObject(scope, "Console");
			scope.put("console", scope, console);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (InvocationTargetException e) {
			throw new RuntimeException(e);
		}
	}

}
